/**
 * @file planner.cpp
 * @author BadFatCat0919 (543015378@qq.com)
 * @brief 方案规划器类
 */

#include "Planner.h"
#include "Path.h"
#include "Params.h"
#include "utils.h"

/**
 * @brief 获得一个方案
 * @param dispatcher 机器人调度器
 * @param benchs 工作台数组
 * @param remainFrames 剩余帧数
 * @return Planner::Plan 方案
 */
Planner::Plan Planner::getPlan(Dispatcher *dispatcher, Bench benchs[], int remainFrames) {
    int robot = dispatcher->getRobot()->getID();
    Plan best;
    bool isNoTime = false;
    for(int buy = 0; buy < Bench::getTotalNumber(); ++buy) {
        if(Path::isArrival_RobotToBench(robot, buy) && benchs[buy].isBuyFree() && benchs[buy].isReady()) { // 寻找可达的未被购买锁定的可生产工作台
            int type = benchs[buy].getType();
            int buyFrames = Path::getDistance_RobotToBench(robot, buy) * PARAMS.STEP_FRAMES_EMPTY;
            buyFrames = utils::max(buyFrames, benchs[buy].getRemainFrames());
            double earning = MATERIAL_EARNING[type];
            for(int sell = 0; sell < Bench::getTotalNumber(); ++sell) {
                if(Path::isArrival_BenchToBench(buy, sell, false) && benchs[sell].isSellFree(type) && benchs[sell].isNeed(type)) { // 寻找可达的未被出售锁定的可出售工作台
                    int sellFrames = Path::getDistance_BenchToBench(buy, sell, false) * PARAMS.STEP_FRAMES_FULL;
                    int frames = buyFrames + sellFrames;
                    if(frames < remainFrames - PARAMS.GAP_FRAMES) {
                        double earningLoss = 0; // 价值损失
                        if(type != 7 && benchs[sell].getType() == 9) { // 如果把非7号货物卖给9号工作台，设置价值损失
                            earningLoss = earning * PARAMS.BENCH9_LOSS_RATE;
                        }
                        Plan plan(type, robot, buy, sell, buyFrames + sellFrames, earning - earningLoss);
                        if(!best.valid || best.earningRate < plan.earningRate) {
                            best = plan;
                        }
                    } else {
                        isNoTime = true;
                    }
                }
            }
        }
    }
    if(!best.valid && isNoTime) {
        best.isNoTime = true;
    }
    return best;
}

/**
 * @brief 工作循环
 * @param dispatchers 机器人调度器数组
 * @param benchs 工作台数组
 * @param remainFrames 剩余帧数
 */
void Planner::loop(Dispatcher dispatchers[], Bench benchs[], int remainFrames) {
    for(int id = 0; id < ROBOT_NUM_MAX; ++id) {
        if(PARAMS.map == 1 && id != 3) {
            continue;
        }
        if(dispatchers[id].isFree()) {
            Robot::pauseAll(); // 所有机器人速度清零，防止跳帧
            Plan plan = getPlan(&dispatchers[id], benchs, remainFrames);
            if(plan.valid) {
                benchs[plan.buy].lockBuy();
                benchs[plan.sell].lockSell(plan.type);
                dispatchers[id].pushCmd(&benchs[plan.buy], &benchs[plan.sell]);
            } else {
                if(plan.isNoTime) {
                    dispatchers[id].pushCmd_Wait(remainFrames);
                } else {
                    dispatchers[id].pushCmd_Wait(PARAMS.REPLAN_FRAMES);
                }
            }
        }
    }
}
